// Math/maths.hpp
#pragma once
#include <core/Types.h>
#include <cmath>


namespace Math
{
const float Pi = 4 * std::atan(1.0f);
const float TwoPi = 2 * Pi;

#ifdef _WIN32
// 0x7fff
//#define RANDOM_MINUS_1_TO_1()	((rand() / (GLfloat)0x3fffffff) - 1.0f) // returns a random value between -1 and 1
#define RANDOM_MINUS_1_TO_1()	((rand() / (GLfloat)0x3fff) - 1.0f) // returns a random value between -1 and 1
//#define RANDOM_0_TO_1() ((rand() / (GLfloat)0x7fffffff))	// returns a random number between 0 and 1
#define RANDOM_0_TO_1() ((rand() / (GLfloat)0x7fff))	// returns a random number between 0 and 1
#else
#define RANDOM_MINUS_1_TO_1()	((random() / (GLfloat)0x3fffffff) - 1.0f) // returns a random value between -1 and 1
#define RANDOM_0_TO_1() ((random() / (GLfloat)0x7fffffff))	// returns a random number between 0 and 1
#endif
#define CLAMP(X, A, B) ((X < A) ? A : ((X > B) ? B : X)) // clamp a value within the defined bounds
#define DEGTORAD(x)	(Math::Pi * ( x * ( 1.0f / 180.0f) ) )
#define RADTODEG(x) ( (x) * (1.0f / Math::Pi) * 180.0f )

#if !defined(MAX)
#define MAX(A, B)		((A) > (B) ? (A) : (B))
#endif

#if !defined(MIN)
#define MIN(A, B)		((A) < (B) ? (A) : (B))
#endif

template <class T>
T Tabi_Clamp(const T & Value, const T & Min, const T & Max)
{
	if (Value < Min)
		return Min;
	else if (Value > Max)
		return Max;

	return Value;
}

template <class T>
inline T Tabi_Min(const T & First, const T & Second)
{
	if (First > Second)
		return Second;
	else
		return First;
}

template <class T>
inline T Tabi_Max(const T & First, const T & Second)
{
	if (Second > First)
		return Second;
	else
		return First;
}

template <class T>
inline T Tabi_Interpolate(float32_t fLambda, const T & Start, const T & End)
{
	return Start + fLambda * (End - Start);
}

// Smoothly interpolate 
template <class T>
T Tabi_InterpolateSmoothed( float32_t fLambda, const T & Start, const T & End )
{
	const float32_t u2 = fLambda * fLambda;
	const float32_t A = 2.0f * u2 * fLambda;
	const float32_t B = 3.0f * u2;

	return Start * ( A - B + 1 ) + End * ( B - A );
}
}; // namespace Math
